package com.aug_leo.datastructure.blockingqueue;

/**
 * 目前队列存在的问题
 * <ol>
 * <li>很多场景要求<b>分离</b>生产者、消费者两个<b>角色</b>、它们得由不同的线程来担当，而之前的实现根本没有考虑线程安全问题</li>
 * <li>队列为空，那么在之前的实现里会返回 null，如果就是硬要拿到一个元素呢？只能不断循环尝试</li>
 * <li>队列为满，那么再之前的实现里会返回 false，如果就是硬要塞入一个元素呢？只能不断循环尝试</li>
 * </ol>
 * <p>
 * 解决方法
 * <ol>
 * <li>用锁保证线程安全</li>
 * <li>用条件变量让 poll 或 offer 线程进入<b>等待</b>状态，而不是不断循环尝试，让 CPU 空转</li>
 * </ol>
 */
public interface BlockingQueue<E> { // 阻塞队列

    /**
     * 将指定元素添加到此队列的尾部。
     * 如果在添加元素时检测到当前线程被中断，则抛出InterruptedException异常。
     *
     * @param e 要添加到队列的元素
     * @throws InterruptedException 如果当前线程在等待添加元素时被中断
     */
    void offer(E e) throws InterruptedException;

    /**
     * 将指定元素添加到此队列的尾部，如果在给定的等待时间内队列未满则成功。
     * 如果在添加元素前检测到当前线程被中断，或者在等待超时后未能添加元素，则抛出InterruptedException异常。
     *
     * @param e       要添加到队列的元素
     * @param timeout 等待添加元素的时间，以毫秒为单位
     * @throws InterruptedException 如果当前线程在等待添加元素时被中断或超时
     */
    boolean offer(E e, long timeout) throws InterruptedException;

    /**
     * 从此队列的头部移除并返回一个元素。
     * 如果在移除元素时检测到当前线程被中断，则抛出InterruptedException异常。
     *
     * @return 从此队列的头部移除的元素
     * @throws InterruptedException 如果当前线程在等待移除元素时被中断
     */
    E poll() throws InterruptedException;
}
